package org.jiucheng.log;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.logging.Formatter;
import java.util.logging.LogRecord;

//import sun.misc.JavaLangAccess;
//import sun.misc.SharedSecrets;

public class StandardFormatter extends Formatter {
    
    private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
    private static StandardFormatter instance;
    
    private Date date = new Date();
    
    static StandardFormatter getInstance() {
        if(null == instance) {
            instance = new StandardFormatter();
        }
        return instance;
    }
    
    private String inferCaller() {
        /*
        JavaLangAccess access = SharedSecrets.getJavaLangAccess();
        Throwable throwable = new Throwable();
        int depth = access.getStackTraceDepth(throwable);
        boolean lookingForLogger = true;
        for (int ix = 0; ix < depth; ix++) {
            // Calling getStackTraceElement directly prevents the VM
            // from paying the cost of building the entire stack frame.
            StackTraceElement frame = access.getStackTraceElement(throwable, ix);
            String cname = frame.getClassName();
            boolean isLoggerImpl = isLoggerImplFrame(cname);
            if (lookingForLogger) {
                // Skip all frames until we have found the first logger frame.
                if (isLoggerImpl) {
                    lookingForLogger = false;
                }
            } else {
                if (!isLoggerImpl) {
                    // skip reflection call
                    if (!cname.startsWith("java.lang.reflect.") && !cname.startsWith("sun.reflect.")) {
                       // We've found the relevant frame.
                       //setSourceClassName(cname);
                       //setSourceMethodName(frame.getMethodName());
                       return frame.toString();
                    }
                }
            }
        }
        */
        return "";
    }
        
    private boolean isLoggerImplFrame(String cname) {
        // the log record could be created for a platform logger
        return (cname.equals("org.jiucheng.log.Logger") || cname.equals("java.util.logging.Logger") ||
                cname.startsWith("java.util.logging.LoggingProxyImpl") ||
                cname.startsWith("sun.util.logging."));
    }
    
    @Override
    public String format(LogRecord record) {
        String source = inferCaller();
        date.setTime(record.getMillis());
        String message = formatMessage(record);
        String throwable = "";
        if (record.getThrown() != null) {
            StringWriter sw = new StringWriter();
            PrintWriter pw = new PrintWriter(sw);
            pw.println();
            record.getThrown().printStackTrace(pw);
            pw.close();
            throwable = sw.toString();
        }
        String newLine = System.getProperty("line.separator");
        if(!throwable.endsWith(newLine)) {
            throwable += newLine;
        }
        return String.format("%s %s %s - <%s>%s", simpleDateFormat.format(date), record.getLevel(), source,  message, throwable);
    }
}
